CloudFormationとCLIで作るEKS環境
はじめに
おはようございます、加藤です。CloudFormationとCLIを使ってEKS環境を作成してみました。
やってみた
環境
- macOS Mojave 10.14.2(18C54)
- Homebrew 1.8.6
クライアント側
ツールのインストール
brew install awscli direnv assume-role jo jq
kubectlのダウンロード
~/bin
に実行ファイルを保存していますが、好みの場所に保存してOKです。
ただし、その場合は関係する箇所を適時読み替えてください。
EKSが対応しているk8sのバージョンは下記の通りです。
- 1.10.3
- 1.11.5
クライアント(kubectl
)、マスターノード、ワーカーノードのバージョンは一致させて使用したいので、全てのバージョンのkubectl
をダウンロードしておきます。
~/bin
にバージョン番号を付与して保存します。
mkdir ~/bin curl -o ~/bin/eks-kubectl-1.10.3 https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/darwin/amd64/kubectl curl -o ~/bin/eks-kubectl-1.11.5 https://amazon-eks.s3-us-west-2.amazonaws.com/1.11.5/2018-12-06/bin/darwin/amd64/kubectl chmod +x ~/bin/eks-kubectl-1.10.3 chmod +x ~/bin/eks-kubectl-1.11.5
~/bin
にkubectl
を保存したのでPATHを通します。
echo 'export PATH=$HOME/bin:$PATH' >> ~/.bash_profile source ~/.bash_profile
aws iam authenticatorのダウンロード
既にPATHを通しているのでダウンロードと実行フラグの設定のみ行います。
curl -o ~/bin/aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/darwin/amd64/aws-iam-authenticator chmod +x ~/bin/aws-iam-authenticator
作業ディレクトリのセットアップ
mkdir ~/workspace/k8s cd ~/workspace/k8s
direnvを使って環境変数を設定します。
assume-roleコマンドでAWS認証情報を環境変数にセットしています。
KUBECONFIG
を設定しない場合は$HOME/.kube/config
に設定が保存されます。私はプロジェクト毎に分離させたい人なので作業ディレクトリ内に保存するよう設定しました。
EKSのバージョンは1.10を使用するので、aliasでkubectl="~/bin/eks-kubectl-1.10.3"
としています。
eval $(assume-role default) export KUBECONFIG='.kube/config' export kubectl="~/bin/eks-kubectl-1.10.3"
サーバー側
BASEの作成
EKSが使用するVPCとControl Plane(マスターノード)が使用するセキュリティグループとIAMロールを作成します。 イミュータブルな部分でここは作成したら変更することが基本的にないはずです。
template-eks-base.yaml
export BASE_STACK_NAME='eks-dev-base' curl -O https://raw.githubusercontent.com/kmd2kmd/cfn-eks/master/template-eks-base.yaml aws cloudformation validate-template --template-body=file://template-eks-base.yaml aws cloudformation create-stack \ --stack-name ${BASE_STACK_NAME} \ --template-body=file://template-eks-base.yaml \ --capabilities CAPABILITY_NAMED_IAM # スタックの完了を待つ aws cloudformation wait stack-create-complete \ --stack-name ${BASE_STACK_NAME} # Outputから必要なパラメータを環境変数に取得しておく。 export CONTROLLPLANE_SECURITYGROUP_IDS=$( \ aws cloudformation describe-stacks \ --stack-name ${BASE_STACK_NAME} | \ jq -r '.Stacks[].Outputs[] | select(.OutputKey == "SecurityGroups")' | \ jq -r '.OutputValue') export VPC_ID=$( \ aws cloudformation describe-stacks \ --stack-name ${BASE_STACK_NAME} | \ jq -r '.Stacks[].Outputs[] | select(.OutputKey == "VpcId")' | \ jq -r '.OutputValue') export SUBNET_IDS=$( \ aws cloudformation describe-stacks \ --stack-name ${BASE_STACK_NAME} | \ jq -r '.Stacks[].Outputs[] | select(.OutputKey == "SubnetIds")' | \ jq -r '.OutputValue') export CLUSTER_ROLE_ARN=$( \ aws cloudformation describe-stacks \ --stack-name ${BASE_STACK_NAME} | \ jq -r '.Stacks[].Outputs[] | select(.OutputKey == "ClusterRoleArn")' | \ jq -r '.OutputValue')
Control Plane の作成
Control Planeを作成します。CFnでも作成が可能ですがアップデートができずCFnで作るメリットが薄いです(初回だけCFnで以降はCLIとなってしまう為)。 なのでCLIで作成します。
export K8S_CLUSTER_NAME="eks-dev-Cluster" export K8S_VERSION='1.10' aws eks create-cluster \ --kubernetes-version ${K8S_VERSION} \ --name ${K8S_CLUSTER_NAME} \ --role-arn ${CLUSTER_ROLE_ARN} \ --resources-vpc-config subnetIds=${SUBNET_IDS},securityGroupIds=${CONTROLLPLANE_SECURITYGROUP_IDS} # クラスターステータスがACTIVEになるのを待つ aws eks describe-cluster --name ${K8S_CLUSTER_NAME} --query cluster.status
Worker Nodes の作成
Worker Nodesを作成します。
template-eks-nodegroup.yaml
NODE_IMAGE_ID(AMI ID)はこちらで確認してください。 Amazon EKSに最適化されたAMI - Amazon EKS
export NODEGROUP_STACK_NAME='eks-dev-nodegroup-000' export KEY_NAME='cm-kato.ryo' export NODE_IMAGE_ID='ami-06f4af3742fca5998' export NODE_VOLUME_SIZE='20' export NODE_GROUP_NAME='eks-nodegroup-001' curl -o https://raw.githubusercontent.com/kmd2kmd/cfn-eks/master/template-eks-nodegroup.yaml jo -a \ $(jo ParameterKey=KeyName ParameterValue=${KEY_NAME}) \ $(jo ParameterKey=NodeImageId ParameterValue=${NODE_IMAGE_ID}) \ $(jo ParameterKey=Subnets ParameterValue=${SUBNET_IDS}) \ $(jo ParameterKey=NodeVolumeSize -s ParameterValue=${NODE_VOLUME_SIZE}) \ $(jo ParameterKey=NodeGroupName ParameterValue=${NODE_GROUP_NAME}) \ $(jo ParameterKey=ClusterControlPlaneSecurityGroup ParameterValue=${CONTROLLPLANE_SECURITYGROUP_IDS}) \ $(jo ParameterKey=VpcId ParameterValue=${VPC_ID}) \ $(jo ParameterKey=ClusterName ParameterValue=${K8S_CLUSTER_NAME}) \ > parameter-eks-nodegroup.json aws cloudformation create-stack \ --stack-name ${NODEGROUP_STACK_NAME} \ --template-body=file://template-eks-nodegroup.yaml \ --parameters=file://parameter-eks-nodegroup.json \ --capabilities CAPABILITY_IAM aws cloudformation wait stack-create-complete \ --stack-name ${NODEGROUP_STACK_NAME} export K8S_NODE_INSTANCE_ROLE=$( \ aws cloudformation describe-stacks \ --stack-name ${NODEGROUP_STACK_NAME} | \ jq -r '.Stacks[].Outputs[] | select(.OutputKey == "NodeInstanceRole")' | \ jq -r '.OutputValue') echo "NodeInstanceRole" echo ${K8S_NODE_INSTANCE_ROLE}
コンフィグ取得
kubectl
が参照するコンフィグを取得します。
KUBECONFIG
を.kube/config
に変更しているので、作業ディレクトリ内に作成されます。
aws eks update-kubeconfig --name ${K8S_CLUSTER_NAME}
Worker NodesをControll Planeと結合
まだ、Controll PlaneからWorker Nodesを認識できていないので結合します。
curl -O https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2018-08-30/aws-auth-cm.yaml sed -i '' -e "s#<ARN of instance role (not instance profile)>#${K8S_NODE_INSTANCE_ROLE}#g" aws-auth-cm.yaml kubectl apply -f aws-auth-cm.yaml
動作確認
サービスの確認
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none>
Worker Nodesの確認
kubectl get nodes
全てのSTATUSがReadyになるのを待ちます。
サンプルアプリケーションのデプロイ
guestbookというサンプルアプリをデプロイします。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-controller.json kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-service.json kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-controller.json kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-service.json kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-service.json
guestbook
のEXTERNAL-IP
を確認して、Webブラウザを開き、httpのポート3000でアクセスします。
kubectl get services -o wide
最後にサンプルアプリを削除します。
kubectl delete rc/redis-master rc/redis-slave rc/guestbook svc/redis-master svc/redis-slave svc/guestbook
あとがき
CloudFormationとCLIでEKS環境を構築してみました!! eksctlを使えば簡単にEKS環境の構築が可能ですが、バージョンアップなども考えるとCFnでやった方が良いかも?と思いやってみました。 CFnでEKSクラスターのアップデートができなかったのが少し残念です。近日中にEKSのバージョンアップ方法についてもブログにします!!